package com.lej.dataservice.club.bean

/**
 * A generic class that holds a value with its loading status.
 * @param <T>
 */
sealed class ApiResult<out R> {
    /**加载更多的时候会用到 [loadEnd] 和 [exception] 记录是否加载完成或者是否加载出错*/
    data class Success<out T>(
        val data: T,
        val loadEnd: Boolean = true,
        val exception: Throwable? = null
    ) : ApiResult<T>()

    data class Error(val exception: Throwable) : ApiResult<Nothing>()
    object Loading : ApiResult<Nothing>()

    val isLoading get() = this is Loading
    val error get() = (this as? Error)?.exception

    @Deprecated("分页列表结果使用 ApiPageResult")
    val isLoadEnd
        get() = this is Success && this.loadEnd

    override fun toString(): String {
        return when (this) {
            is Success<*> -> "Success[data=$data]"
            is Error -> "Error[exception=$exception]"
            is Loading -> "Loading"
        }
    }

    val value: R?
        get() = when (this) {
            is Success<R> -> data
            else -> null
        }
}

const val FETCH_TYPE_NONE = 0x00
const val FETCH_TYPE_REFRESH = 0x11
const val FETCH_TYPE_LOAD_MORE = 0x01
const val FETCH_TYPE_UP_FETCH = 0x10

class ApiPageResult<T>(
    var data: MutableList<T> = mutableListOf(),
    ///是否加载结束
    var loadEnd: Boolean = false,
    var exception: Throwable? = null,
    ///加载更多用的临时列表
    var tempList: List<T>? = null,
    var page: Int = 1,
    ///是否加载中 -1是没有加载
    var loading: Boolean = true,
    /**-1是不知道，0是刷新 1是上啦加载更多[加到下面]  2是下拉加载更多[加到上面]*/
    var fetchType: Int = -1
) {
    val isError get() = exception != null
    val isRefreshError get() = exception != null && page == 1
    val isLoadError get() = exception != null && page > 1

    /**是否刷新中*/
    val isRefreshing get() = loading && fetchType == FETCH_TYPE_REFRESH

    /**是否上啦加载*/
    val isLoading get() = loading && fetchType == FETCH_TYPE_LOAD_MORE

    /**是否下拉加载*/
    val isFetching get() = loading && fetchType == FETCH_TYPE_UP_FETCH

}

fun <T> ApiPageResult<T>?.error(page: Int = 1, exception: Throwable, fetchType: Int? = null): ApiPageResult<T> {
    return (this ?: ApiPageResult()).apply {
        this.loading = false
        this.fetchType = if (page == 1) FETCH_TYPE_REFRESH else FETCH_TYPE_LOAD_MORE
        this.exception = exception
    }
}

fun <T> ApiPageResult<T>?.Loading(page: Int = 1, fetchType: Int? = null): ApiPageResult<T> {
    return (this ?: ApiPageResult()).apply {
        this.page = page
        this.loading = true
        this.fetchType = fetchType ?: if (page == 1) FETCH_TYPE_REFRESH else FETCH_TYPE_LOAD_MORE
        this.exception = null
        this.tempList = null
    }
}

fun <T> ApiPageResult<T>?.refreshing(): ApiPageResult<T> = Loading(1, fetchType = FETCH_TYPE_REFRESH)
fun <T> ApiPageResult<T>?.loadingMore(page: Int): ApiPageResult<T> = Loading(page, fetchType = FETCH_TYPE_LOAD_MORE)
fun <T> ApiPageResult<T>?.fetching(page: Int): ApiPageResult<T> = Loading(page, fetchType = FETCH_TYPE_UP_FETCH)

/**[addPrefix] 是否加为前缀，（加到前面去） [ApiPageResult.fetchType]*/
fun <T> ApiPageResult<T>?.success(page: Int = 1, data: List<T>, loadEnd: Boolean? = null, addPrefix: Boolean = false, fetchType: Int? = null): ApiPageResult<T> {
    return (this ?: ApiPageResult()).apply {
        this.page = page
        this.loading = false
        this.fetchType = fetchType ?: if (page == 1) FETCH_TYPE_REFRESH else FETCH_TYPE_LOAD_MORE
        exception = null

        //data 第一页先清空
        if (page == 1) this.data.clear()

        this.data.apply { if (addPrefix) addAll(0, data) else addAll(data) }
//        ///创建新数组,避免和adapter的数组使用同一 数组对象,引起更改问题   使用同一个数组
//        this.data = this.data.toMutableList()

        ///loadEnd
        this.loadEnd = loadEnd ?: data.isNullOrEmpty()

        tempList = data
    }
}

///列表结果加内容
@Deprecated(message = "用 ApiPageResult 这个吧")
inline fun <reified T> ApiResult<MutableList<T>>?.addListData(list: List<T>?): MutableList<T> =
    ///避免同一个数组  toMutableList 创建新数组
    (this?.value?.toMutableList()
        ?: mutableListOf<T>()).apply { list?.let { addAll(list.toMutableList()) } }


